package org.zephyr.fastboot.config.security;

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
import org.zephyr.fastboot.constant.ResultType;
import org.zephyr.fastboot.entity.SysUser;
import org.zephyr.fastboot.exception.JwtValidationException;
import org.zephyr.fastboot.service.SysUserService;
import org.zephyr.fastboot.util.JwtUtil;

/**
 * @Author: ZephyrGao
 * @Date: 2024/6/18 17:58
 * @Description: 用于处理JwtToken的认证和授权
 */
@Slf4j
@Component
public class JwtRealm extends AuthorizingRealm {

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private SysUserService userService;

    /**
     * 多重写一个support
     * 标识这个Realm是专门用来验证JwtToken
     */
//    @Override
//    public boolean supports(AuthenticationToken token) {
//        return token instanceof JwtToken;
//    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("开始进行权限认证[roles,permission]" + principals.toString());

        // 权限认证
        String username = (String) principals.getPrimaryPrincipal();
        SysUser user = userService.getUserByName(username);
        return null;
//        return new SimpleAuthorizationInfo();

        // 假设PrincipalCollection中包含了一个用户名字符串
//        String username = (String) principalCollection.getPrimaryPrincipal();

        // 使用用户名从某个服务（如UserService）中获取用户角色
        // 注意：这里需要您有一个UserService或类似的服务来执行此操作
//        Set<String> roles = new HashSet<>();
//        roles.add("ROLE_ADMIN");
//        roles.add("ROLE_USER");
//        roles.add("ROLE_GUEST"); // 注意：如果HashSet中已存在相同元素，则不会重复添加
//
//        // 创建AuthorizationInfo实例并添加角色
//        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//        authorizationInfo.addRoles(roles);
//
//        // 如果您还需要添加权限，也可以这样做：
//        // Set<String> permissions = userService.findPermissionsByUsername(username);
//        // authorizationInfo.addStringPermissions(permissions);
//
//        // 返回包含角色（和可选的权限）的AuthorizationInfo对象
//        return authorizationInfo;
    }

    /**
     * 认证逻辑
     * 一般用户自定义登录，shiro的底层会调用该类的认证方法进行认证
     * 该方法只是获取的对比信息，具体的认证逻辑需要自己实现
     * 例如：从数据库中获取用户信息，然后与传入的用户名和密码进行对比
     * 注意：该方法需要返回一个AuthenticationInfo对象，该对象包含了认证后的用户信息
     * 例如：用户名和密码，以及用户的角色和权限信息
     * 该方法会抛出AuthenticationException异常，如果认证失败
     * 例如：用户名或密码错误
     * 注意：该方法需要被@Override注解
     *
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 身份验证
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        // 这里应根据实际情况查询数据库验证用户身份
        if ("admin".equals(username) && "admin".equals(password)) {
            return new SimpleAuthenticationInfo(username, password, getName());
        } else {
            throw new AuthenticationException("用户名或密码错误");
        }
        // 获取身份信息
//        String principal = authenticationToken.getPrincipal().toString();
//        System.out.println("principal = " + principal);
//        // 获取凭证信息
//        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
//        String username = upToken.getUsername();
//        String password = new String(upToken.getPassword());
//
//        String jwt = (String) authenticationToken.getCredentials();
//        // 获取jwt中关于用户id，解码过程中如果token过期或者被篡改会抛出异常
////        String id = null;
//        log.info("处理jwt认证", jwt);
//        try {
//            // Validate the token
//            String id = JwtUtil.validateToken(jwt);
//            log.info("jwt认证成功，用户id：", id);
//            // 标记用户为活跃状态
////            userService.markUserActive(Integer.parseInt(id));
//            return new SimpleAuthenticationInfo(jwt, jwt, getName());
//        }
//        catch (ExpiredJwtException e) {
//            throw new JwtValidationException(ResultType.UNAUTHORIZED.getCode(), "Token已过期，请重新登录");
//        } catch (JwtException e) {
//            throw new JwtValidationException(ResultType.UNAUTHORIZED.getCode(), "无效的Token");
//        }
    }

}
